package com.zwd.deep.handle.exception;

import com.zwd.deep.common.RequestResult;
import com.zwd.deep.common.ResultEnum;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.util.LinkedHashMap;
import java.util.Map;


/**
 * 全局异常处理器
 *
 * @author wanjunhong
 */
@Order(1)
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 全局异常处理
     */
    @ExceptionHandler({GlobalException.class, Exception.class})
    public RequestResult<Void> globalExceptionHandler(HttpServletRequest request,
                                                      Exception ex) {
        if (ex instanceof GlobalException) {
            ResultEnum resultEnum = ResultEnum.valueOf(ex.getMessage());
            log.error("请求{}时异常:{}", request.getRequestURI(), resultEnum.getMsg());
            return RequestResult.fail(resultEnum);
        } else {
            log.error("请求{}时异常:", request.getRequestURI());
            ex.printStackTrace();
            //TODO 后续上线后可以记录异常日志 并通知在群里
            return RequestResult.fail(ResultEnum.SYSTEM_ERROR);
        }
    }

    /**
     * 404异常处理,上面的全局处理器捕获了NoResourceFoundException，导致接口返回500错误，
     * 会误导，所以这里单独处理
     */
    @ExceptionHandler(NoResourceFoundException.class)
    public RequestResult<Void> noResourceFoundExceptionHandler(HttpServletRequest request,
                                                               NoResourceFoundException ex) {

        log.error("请求{}时异常:", request.getRequestURI());
        ex.printStackTrace();
        //TODO 后续可以直接返回404页面
        return RequestResult.fail(ResultEnum.NO_RESOURCE_FOUND);
    }
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public RequestResult<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new LinkedHashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        log.error("参数校验异常: {}", errors);
//        return RequestResult.fail(ResponseEntity.badRequest().body(errors));
        return RequestResult.fail(errors);
    }
}
